#include "Keyboard.h"

//Define the max size of the keyboard buffer as a constant
const static unsigned kuiInputBufferSize = 128;


//Initializate the keyboard input
void cKeyboard::Init()
{
  //Initializate the mabKeyboardInput 
  memset(mabInputBuffer, 0, kuiInputChannelSize);

  //Get the standard input handler
  mStdin = GetStdHandle(STD_INPUT_HANDLE);
  if (mStdin == INVALID_HANDLE_VALUE)
  {
    std::cout << "Error: GetStdHandle" << std::endl;
    return;
  }

  //Save the current input mode to be restored on exit
  if (!GetConsoleMode(mStdin, &mOldModeSaved) ) 
  {
    std::cout << "Error: GetConsoleMode" << std::endl;
    return;
  }

  //Enable the window input events
  DWORD lNewMode = ENABLE_WINDOW_INPUT;
  if (!SetConsoleMode(mStdin, lNewMode) )
  {
    std::cout << "Error: SetConsoleMode" << std::endl;
  }

  //Sucessfull initialization
  mbIsValid = true;
}


//Deinitializate the keyboard input and restore the original controller
void cKeyboard::Deinit()
{
  if (!SetConsoleMode(mStdin, mOldModeSaved))
  {
    std::cout << "Error: SetConsoleMode" << std::endl;
  }
  
  //Establish the state of the class to uninitialized
  mbIsValid = false;
}


//Update 
void cKeyboard::Update()
{
  INPUT_RECORD laInBuf[ kuiInputBufferSize ];
  DWORD luiNumRead;

  //Check for available events
  if (!PeekConsoleInput( mStdin, laInBuf, kuiInputBufferSize, &luiNumRead))
  {
    std::cout << "Error: PeekConsoleInput" << std::endl;
    return;
  }

  //No new events
  if (luiNumRead <=0) 
    return;

  //Read the events into the events the local buffer and clear the buffer of events
  if (!ReadConsoleInput( mStdin, laInBuf, kuiInputBufferSize, &luiNumRead))
  {
    std::cout << "Error: ReadConsoleInput" << std::endl;
    return;
  }

  //Process every event using the appropiate handler
  for (unsigned luiIndex = 0; luiIndex < luiNumRead; luiIndex++)
  {
    if (laInBuf[luiIndex].EventType == KEY_EVENT)
      KeyEventProc(laInBuf[luiIndex].Event.KeyEvent);
  }
}


//Getter to obtain the state of a key
float cKeyboard::Check(unsigned int luiEntry)
{
  if (mabInputBuffer[luiEntry])
    return 1.0f;
  return 0.0f;
}


//Return the state of the initialization 
bool cKeyboard::IsValid()
{
  return mbIsValid;
}


//Private method. Change the state of the key pressed
void cKeyboard::KeyEventProc(KEY_EVENT_RECORD lKey)
{
  if (lKey.wVirtualKeyCode >= 0 && lKey.wVirtualKeyCode < kuiInputChannelSize)
    mabInputBuffer[lKey.wVirtualKeyCode] = (lKey.bKeyDown == TRUE);
}